package org.apimgr.service;

import org.apimgr.dto.*;
import org.apimgr.entity.*;
import org.apimgr.enums.PTExceptionCode;
import org.apimgr.exception.PTUnCheckedException;
import org.apimgr.mapper.*;
import org.apimgr.util.ConstantsUtil;
import org.apimgr.util.FileUtil;
import org.apimgr.util.RemoteUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.List;

/**
 * Created by yangjie on 2017/8/1.
 * API项目Service
 */
@Service
public class ApiProjectService {

    @Resource
    private ApiProjectMapper apiProjectMapper;

    @Resource
    private LoginService loginService;

    @Resource
    private ApiContentMapper apiContentMapper;

    @Resource
    private ApiResponseMapper apiResponseMapper;

    @Resource
    private ApiRequestParamDescMapper apiRequestParamDescMapper;

    @Resource
    private ApiResponseDescMapper apiResponseDescMapper;

    /**
     * 多条件查询Api项目信息
     *
     * @param reqDto
     * @return
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public ApiProjectResDto getApiProjectByParam(ApiProjectReqDto reqDto, String token) {
        ApiProjectResDto resDto = new ApiProjectResDto();
        List<ApiProject> apiProjectList = apiProjectMapper.getApiProjectByParams(reqDto);
        ApiUser loginUser = loginService.getLoginUser(token);
        reqDto.setUser_id(loginUser.getId());
        resDto.setApiProjectList(apiProjectList);
        return resDto;
    }

    /**
     * 添加Api项目信息
     *
     * @param reqDto
     * @return
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public ApiProjectResDto addApiProject(ApiProjectReqDto reqDto) {
        ApiProjectResDto resDto = new ApiProjectResDto();
        try {
            int i = apiProjectMapper.addApiProject(reqDto);
            if (i == 0) {
                throw new PTUnCheckedException(PTExceptionCode.BD_INSERT_EXPT.getCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new PTUnCheckedException(PTExceptionCode.BD_INSERT_EXPT.getCode());
        }
        return resDto;
    }


    /**
     * 修改Api项目信息
     *
     * @param reqDto
     * @return
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public ApiProjectResDto updateApiProject(ApiProjectReqDto reqDto) {
        ApiProjectResDto resDto = new ApiProjectResDto();
        try {
            int i = apiProjectMapper.updateApiProject(reqDto);
            if (i == 0) {
                throw new PTUnCheckedException(PTExceptionCode.BD_UPDATE_EXPT.getCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new PTUnCheckedException(PTExceptionCode.BD_UPDATE_EXPT.getCode());
        }
        return resDto;
    }


    /**
     * 删除Api项目信息
     *
     * @param reqDto
     * @return
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public ApiProjectResDto deleteApiProject(ApiProjectReqDto reqDto) {
        ApiProjectResDto resDto = new ApiProjectResDto();
        try {
            int i = apiProjectMapper.deleteApiProject(reqDto);
            if (i == 0) {
                throw new PTUnCheckedException(PTExceptionCode.BD_DELETE_EXPT.getCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new PTUnCheckedException(PTExceptionCode.BD_DELETE_EXPT.getCode());
        }
        return resDto;
    }

    /**
     * 将接口列表导出成Html
     *
     * @param reqDto
     * @param response
     */
    public void exportHtml(ApiProjectReqDto reqDto, HttpServletRequest request, HttpServletResponse response) {
        try {

            List<ApiProject> projectList = apiProjectMapper.getApiProjectByParams(reqDto);
            ApiProject apiProject = null;
            if(projectList != null && projectList.size() > 0){
                apiProject = projectList.get(0);
            }

            if(apiProject != null) {

                String deskTopPath = FileUtil.getDeskTopPath();
                RemoteUtil.downloadFile(ConstantsUtil.BOOTSTRAP_CSS_URL, deskTopPath + "\\" + apiProject.getProject_name() + ConstantsUtil.EXPORT_BOOTSTRAP_CSS_PATH);
                RemoteUtil.downloadFile(ConstantsUtil.BOOTSTRAP_JS_URL, deskTopPath + "\\" + apiProject.getProject_name() + ConstantsUtil.EXPORT_BOOTSTRAP_JS_PATH);
                RemoteUtil.downloadFile(ConstantsUtil.JQUERY_URL, deskTopPath + "\\" + apiProject.getProject_name() + ConstantsUtil.EXPORT_JQUERY_PATH);


                ApiContentReqDto apiContentReqDto = new ApiContentReqDto();
                apiContentReqDto.setProject_id(reqDto.getId());

                List<ApiContent> apiContentList = apiContentMapper.getApiContentByParams(apiContentReqDto);
                for (ApiContent apiContent : apiContentList) {

                    //查询请求参数说明的列表
                    ApiRequestParamDescReqDto apiRequestParamDescReqDto = new ApiRequestParamDescReqDto();
                    apiRequestParamDescReqDto.setContent_id(apiContent.getId());
                    List<ApiRequestParamDesc> paramDescList = apiRequestParamDescMapper.getApiRequestParamDescByParams(apiRequestParamDescReqDto);

                    //查询请求返回列表
                    ApiResponseReqDto apiResponseReqDto = new ApiResponseReqDto();
                    apiResponseReqDto.setApi_content_id(apiContent.getId());
                    List<ApiResponse> responseList = apiResponseMapper.getApiResponseByParams(apiResponseReqDto);

                    for (ApiResponse apiResponse : responseList) {
                        if (apiResponse.getResponse_type() == ConstantsUtil.RIGHT_RESPONSE_CODE) {
                            ApiResponseDescReqDto apiResponseDescReqDto = new ApiResponseDescReqDto();
                            apiResponseDescReqDto.setResponse_id(apiResponse.getId());
                            List<ApiResponseDesc> apiResponseDescList = apiResponseDescMapper.getApiResponseDescByParams(apiResponseDescReqDto);
                            String htmlStr = getExportHtmlByProjectId(apiContent, paramDescList, responseList, apiResponseDescList, apiContentList);
                            File file = new File(deskTopPath + "\\" + apiProject.getProject_name() + "\\" + apiContent.getApi_name() + ".html");
                            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
                            bw.write(htmlStr);
                            bw.flush();
                            bw.close();
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 导出APi接口的Html文本
     *
     * @param apiContent          当前API接口
     * @param apiContentList      API接口列表
     * @param paramDescList       请求参数说明List
     * @param apiResponseDescList API响应描述List
     * @return
     */
    public String getExportHtmlByProjectId(ApiContent apiContent, List<ApiRequestParamDesc> paramDescList,
                                           List<ApiResponse> responseList, List<ApiResponseDesc> apiResponseDescList,
                                           List<ApiContent> apiContentList) {
        StringBuffer sb = new StringBuffer();
        StringBuffer leftMenuSb = new StringBuffer();
        StringBuffer reqParamDescSb = new StringBuffer();
        StringBuffer responsecSb = new StringBuffer();
        StringBuffer rightResponseSb = new StringBuffer();
        StringBuffer wrongResponseSb = new StringBuffer();
        StringBuffer wrongEnumResJsonSb = new StringBuffer();
        StringBuffer responseDesccSb = new StringBuffer();

        //左侧树的添加
        for (ApiContent content : apiContentList) {
            if(content.getApi_name().equals(apiContent.getApi_name())) {
                leftMenuSb.append("<dl class=\"system_log\">\n" +
                        "\t\t\t\t\t<dt style=\"background-color: #006666;\">" + content.getApi_name() + "</dt>\n" +
                        "\t\t\t\t</dl>");
            }else{
                leftMenuSb.append("<dl class=\"system_log\">\n" +
                        "\t\t\t\t\t<dt>" + content.getApi_name() + "</dt>\n" +
                        "\t\t\t\t</dl>");
            }
        }


        for (ApiRequestParamDesc apiRequestParamDesc : paramDescList) {
            reqParamDescSb.append("<tr>\n" +
                    "\t\t\t\t\t\t<td>" + apiRequestParamDesc.getRequest_param_name() + "</td>\n" +
                    "\t\t\t\t\t\t<td>" + apiRequestParamDesc.getData_type() + "</td>\n" +
                    "\t\t\t\t\t\t<td>" + (apiRequestParamDesc.getIs_required() ? "true" : "false") + "</td>\n" +
                    "\t\t\t\t\t\t<td>" + apiRequestParamDesc.getReq_param_desc() + "</td>\n" +
                    "\t\t\t\t\t</tr>");
        }


        //添加响应数据
        responsecSb.append("<br />\n" +
                "\t\t\t\t<h4 class=\"text-danger\">返回实例</h4>\n" +
                "\t\t\t\t<br />\n");
        for (ApiResponse apiResponse : responseList) {
            if (apiResponse.getResponse_type() == ConstantsUtil.RIGHT_RESPONSE_CODE) {
                rightResponseSb.append("\t\t\t\t<h5 class=\"text-primary\">&nbsp;&nbsp;&nbsp;正确返回</h5> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n" +
                        "\t\t\t\t<textarea cols=\"150\" rows=\"20\" style=\"border-radius: 5px;\" readonly=\"readonly\">" + apiResponse.getResponse_content() + "</textarea>\n" +
                        "\t\t\t\t<br />\n");
            } else {
                wrongResponseSb.append("\t\t\t\t<h5 class=\"text-danger\">&nbsp;&nbsp;&nbsp;错误返回</h5> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n" +
                        "\t\t\t\t<textarea cols=\"150\" rows=\"20\" style=\"border-radius: 5px;\" readonly=\"readonly\">" + apiResponse.getResponse_content() + "</textarea>\n" +
                        "\t\t\t\t<br />\n");
                wrongEnumResJsonSb.append("\t\t\t\t<h5 class=\"text-danger\">&nbsp;&nbsp;&nbsp;错误信息枚举</h5> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n" +
                        "\t\t\t\t<textarea cols=\"150\" rows=\"10\" style=\"border-radius: 5px;\" readonly=\"readonly\">" + apiResponse.getWrong_enum() + "</textarea><br />\n" +
                        "\t\t\t\t<br />");
            }
        }
        responsecSb.append(rightResponseSb);
        responsecSb.append(wrongResponseSb);
        responsecSb.append(wrongEnumResJsonSb);


        for (ApiResponseDesc apiResponseDesc : apiResponseDescList) {
            responseDesccSb.append("<tr>\n" +
                    "\t\t\t\t\t\t<td>" + apiResponseDesc.getParam_name() + "</td>\n" +
                    "\t\t\t\t\t\t<td>" + apiResponseDesc.getParam_type() + "</td>\n" +
                    "\t\t\t\t\t\t<td>" + apiResponseDesc.getParam_desc() + "</td>\n" +
                    "\t\t\t\t\t</tr>");
        }


        sb.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" +
                "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" +
                "\n" +
                "\t<head>\n" +
                "\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n" +
                "\t\t<title>"+apiContent.getApi_name()+"</title>\n" +
                "\n" +
                "\t\t<head>\n" +
                "\t\t\t<link rel=\"stylesheet\" href=\"bootstrap/bootstrap.css\" />\n" +
                "\t\t\t<style type=\"text/css\">\n" +
                "\t\t\t\tbody {\n" +
                "\t\t\t\t\tmargin: 0;\n" +
                "\t\t\t\t\tpadding: 0;\n" +
                "\t\t\t\t\toverflow-x: hidden;\n" +
                "\t\t\t\t}\n" +
                "\t\t\t\ttextarea{\n" +
                "\t\t\t\t\tfont-size: 16px;\n" +
                "\t\t\t\t}" +
                "\t\t\t\t\n" +
                "\t\t\t\thtml,\n" +
                "\t\t\t\tbody {\n" +
                "\t\t\t\t\theight: 100%;\n" +
                "\t\t\t\t}\n" +
                "\t\t\t\t\n" +
                "\t\t\t\timg {\n" +
                "\t\t\t\t\tborder: none;\n" +
                "\t\t\t\t}\n" +
                "\t\t\t\t\n" +
                "\t\t\t\t* {\n" +
                "\t\t\t\t\tfont-family: '微软雅黑';\n" +
                "\t\t\t\t\tfont-size: 12px;\n" +
                "\t\t\t\t\tcolor: #626262;\n" +
                "\t\t\t\t}\n" +
                "\t\t\t\t\n" +
                "\t\t\t\tdl,\n" +
                "\t\t\t\tdt,\n" +
                "\t\t\t\tdd {\n" +
                "\t\t\t\t\tdisplay: block;\n" +
                "\t\t\t\t\tmargin: 0;\n" +
                "\t\t\t\t}\n" +
                "\t\t\t\t\n" +
                "\t\t\t\ta {\n" +
                "\t\t\t\t\ttext-decoration: none;\n" +
                "\t\t\t\t}\n" +
                "\t\t\t\t\n" +
                "\t\t\t\t.container {\n" +
                "\t\t\t\t\twidth: 100%;\n" +
                "\t\t\t\t\theight: 100%;\n" +
                "\t\t\t\t\tmargin: auto;\n" +
                "\t\t\t\t}\n" +
                "\t\t\t\t/*left*/\n" +
                "\t\t\t\t\n" +
                "\t\t\t\t.leftsidebar_box {\n" +
                "\t\t\t\t\twidth: 160px;\n" +
                "\t\t\t\t\theight: auto !important;\n" +
                "\t\t\t\t\toverflow: visible !important;\n" +
                "\t\t\t\t\tposition: fixed;\n" +
                "\t\t\t\t\theight: 100% !important;\n" +
                "\t\t\t\t\tbackground-color: #3992d0;\n" +
                "\t\t\t\t}\n" +
                "\t\t\t\t\n" +
                "\t\t\t\t.line {\n" +
                "\t\t\t\t\theight: 2px;\n" +
                "\t\t\t\t\twidth: 100%;\n" +
                "\t\t\t\t\tbackground-repeat: repeat-x;\n" +
                "\t\t\t\t}\n" +
                "\t\t\t\t\n" +
                "\t\t\t\t.leftsidebar_box dt {\n" +
                "\t\t\t\t\tpadding-left: 40px;\n" +
                "\t\t\t\t\tpadding-right: 10px;\n" +
                "\t\t\t\t\tbackground-repeat: no-repeat;\n" +
                "\t\t\t\t\tbackground-position: 10px center;\n" +
                "\t\t\t\t\tcolor: #f5f5f5;\n" +
                "\t\t\t\t\tfont-size: 14px;\n" +
                "\t\t\t\t\tposition: relative;\n" +
                "\t\t\t\t\tline-height: 48px;\n" +
                "\t\t\t\t\tcursor: pointer;\n" +
                "\t\t\t\t}\n" +
                "\t\t\t\t\n" +
                "\t\t\t\t.leftsidebar_box dd {\n" +
                "\t\t\t\t\tbackground-color: #317eb4;\n" +
                "\t\t\t\t\tpadding-left: 40px;\n" +
                "\t\t\t\t}\n" +
                "\t\t\t\t\n" +
                "\t\t\t\t.leftsidebar_box dd a {\n" +
                "\t\t\t\t\tcolor: #f5f5f5;\n" +
                "\t\t\t\t\tline-height: 20px;\n" +
                "\t\t\t\t}\n" +
                "\t\t\t\t\n" +
                "\t\t\t\t.leftsidebar_box dt img {\n" +
                "\t\t\t\t\tposition: absolute;\n" +
                "\t\t\t\t\tright: 10px;\n" +
                "\t\t\t\t\ttop: 20px;\n" +
                "\t\t\t\t}\n" +
                "\t\t\t\t\n" +
                "\t\t\t\t.leftsidebar_box dl dd:last-child {\n" +
                "\t\t\t\t\tpadding-bottom: 10px;\n" +
                "\t\t\t\t}\n" +
                "\t\t\t\t\n" +
                "\t\t\t\t.rightBody table tr td {\n" +
                "\t\t\t\t\tfont-size: 16px;\n" +
                "\t\t\t\t}\n" +
                "\t\t\t\t\n" +
                "\t\t\t\ttr {\n" +
                "\t\t\t\t\ttext-align: center;\n" +
                "\t\t\t\t}\n" +
                "\t\t\t</style>\n" +
                "\n" +
                "\t\t</head>\n" +
                "\n" +
                "\t\t<body id=\"bg\">\n" +
                "\n" +
                "\t\t\t<div class=\"leftsidebar_box\">\n" +
                "\t\t\t\t<div class=\"line\"></div>\n"
        );
        sb.append(leftMenuSb);
        sb.append("\t\t\t</div>\n" +
                "\n" +
                "\t\t\t<div class=\"rightBody\" style=\"width: 70%;height: 100px;margin-left: 20%;transform: translateY(50px);\">\n" +
                "\t\t\t\t<table class=\"table table-bordered\" width=\"80%\">\n" +
                "\t\t\t\t\t<tr align=\"center\">\n" +
                "\t\t\t\t\t\t<td>API接口名称</td>\n" +
                "\t\t\t\t\t\t<td>" + apiContent.getApi_name() + "</td>\n" +
                "\t\t\t\t\t</tr>\n" +
                "\t\t\t\t\t<tr>\n" +
                "\t\t\t\t\t\t<td>API接口说明</td>\n" +
                "\t\t\t\t\t\t<td>" + apiContent.getApi_desc() + "</td>\n" +
                "\t\t\t\t\t</tr>\n" +
                "\n" +
                "\t\t\t\t\t<tr>\n" +
                "\t\t\t\t\t\t<td>API接口Url</td>\n" +
                "\t\t\t\t\t\t<td>" + apiContent.getRequest_url() + "</td>\n" +
                "\t\t\t\t\t</tr>\n" +
                "\n" +
                "\t\t\t\t\t<tr>\n" +
                "\t\t\t\t\t\t<td>API接口请求方式</td>\n" +
                "\t\t\t\t\t\t<td>" + apiContent.getRequest_method() + "</td>\n" +
                "\t\t\t\t\t</tr>\n" +
                "\n" +
                "\t\t\t\t\t<tr>\n" +
                "\t\t\t\t\t\t<td>API接口请求头</td>\n" +
                "\t\t\t\t\t\t<td>" + apiContent.getRequest_head() + "</td>\n" +
                "\t\t\t\t\t</tr>\n" +
                "\n" +
                "\t\t\t\t\t<tr>\n" +
                "\t\t\t\t\t\t<td>请求参数</td>\n" +
                "\t\t\t\t\t\t<td>\n" +
                "\t\t\t\t\t\t\t<textarea cols=\"70\" rows=\"20\" readonly=\"readonly\">" + apiContent.getRequest_param() + "</textarea>\n" +
                "\t\t\t\t\t\t</td>\n" +
                "\t\t\t\t\t</tr>\n" +
                "\t\t\t\t</table>");

        //添加参数描述
        sb.append("<br />\n" +
                "\t\t\t\t<h4 class=\"text-danger\">请求参数说明</h4>\n" +
                "\t\t\t\t<table class=\"table table-bordered\" width=\"80%\">\n" +
                "\t\t\t\t\t<tr>\n" +
                "\t\t\t\t\t\t<td>参数名称</td>\n" +
                "\t\t\t\t\t\t<td>数据类型</td>\n" +
                "\t\t\t\t\t\t<td>是否必填</td>\n" +
                "\t\t\t\t\t\t<td>参数描述</td>\n" +
                "\t\t\t\t\t</tr>\n"
        );
        sb.append(reqParamDescSb);
        sb.append("\t\t\t\t</table>");
        sb.append(responsecSb);
        sb.append("\t<h4 class=\"text-danger\">返回参数说明</h4>\n" +
                "\t\t\t\t<table class=\"table table-bordered\" width=\"80%\">\n" +
                "\t\t\t\t\t<tr>\n" +
                "\t\t\t\t\t\t<td>参数名称</td>\n" +
                "\t\t\t\t\t\t<td>数据类型</td>\n" +
                "\t\t\t\t\t\t<td>参数描述</td>\n" +
                "\t\t\t\t\t</tr>");
        sb.append(responseDesccSb);
        sb.append("</table>");

        sb.append("</div>");

        sb.append("\n" +
                "\t\t\t<script type=\"text/javascript\" src=\"bootstrap/jquery.js\"></script>\n" +
                "\t\t\t<script type=\"text/javascript\">\n" +
                "\t\t\t\t\n" +
                "\t\t\t\t$(\".system_log\").click(function(){\n" +
                "\t\t\t\t\tlet href = $(this).find(\"dt\").html()+\".html\";\n" +
                "\t\t\t\t\twindow.location = href;\n" +
                "\t\t\t\t})\n" +
                "\t\t\t\t\n" +
                "\t\t\t\t$(function() {\n" +
                "\t\t\t\t\t$(\".leftsidebar_box dd\").hide();\n" +
                "\t\t\t\t\t$(\".leftsidebar_box dt\").click(function() {\n" +
                "\t\t\t\t\t\t$(\".leftsidebar_box dt\").css({ \"background-color\": \"#006666\" })\n" +
                "\t\t\t\t\t\t$(this).css({ \"background-color\": \"#317eb4\" });\n" +
                "\t\t\t\t\t\t$(this).parent().find('dd').removeClass(\"menu_chioce\");\n" +
                "\t\t\t\t\t\t$(\".leftsidebar_box dt img\").attr(\"src\", \"images/left/select_xl01.png\");\n" +
                "\t\t\t\t\t\t$(this).parent().find('img').attr(\"src\", \"images/left/select_xl.png\");\n" +
                "\t\t\t\t\t\t$(\".menu_chioce\").slideUp();\n" +
                "\t\t\t\t\t\t$(this).parent().find('dd').slideToggle();\n" +
                "\t\t\t\t\t\t$(this).parent().find('dd').addClass(\"menu_chioce\");\n" +
                "\t\t\t\t\t});\n" +
                "\t\t\t\t})\n" +
                "\t\t\t</script>\n" +
                "\t\t</body>\n" +
                "\n" +
                "</html>");
        return sb.toString();
    }
}
